import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.stream.Collectors;

public class FoodNameFetcher {

    // 假设这里有一个方法，根据食品分类查询食品名字的实现
    // 这里用一个简单的模拟方法来代替
    public static List<String> fetchFoodNamesByCategory(String category) {
        // 模拟查询，实际应用中可以是数据库查询或者其他异步操作
        try {
            Thread.sleep(1000); // 模拟耗时操作
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
        return Arrays.asList(category + "_Food1", category + "_Food2", category + "_Food3");
    }

    public static void main(String[] args) {
        // 定义食品分类列表
        List<String> foodCategories = Arrays.asList("Fruit", "Vegetable", "Meat");

        // 创建一个自定义的线程池，这里使用固定大小的线程池
        ExecutorService customThreadPool = Executors.newFixedThreadPool(foodCategories.size());

        // 使用CompletableFuture实现并行查询
        List<CompletableFuture<List<String>>> futures = foodCategories.stream()
                .map(category -> CompletableFuture.supplyAsync(() -> fetchFoodNamesByCategory(category), customThreadPool))
                .collect(Collectors.toList());

        // 等待所有CompletableFuture完成
        CompletableFuture<Void> allFutures = CompletableFuture.allOf(
                futures.toArray(new CompletableFuture[futures.size()]));

        // 处理每个CompletableFuture的结果
        /**
         * allFutures 是什么？
         *
         * allFutures 是一个 CompletableFuture<Void> 对象，它通过 CompletableFuture.allOf() 等待一组 CompletableFuture 对象全部完成。
         * thenApply 方法：
         *
         * thenApply 方法是 CompletableFuture 类中的方法，它会在当前 CompletableFuture 完成后执行一个函数，并返回一个新的 CompletableFuture 对象，该对象包含函数的返回值。
         * Lambda 表达式 (v -> ...)：
         *
         * 这里的 v 是一个占位符，表示在 allFutures 完成后传递的值（这里是 Void，即没有具体的值）。
         * 在 lambda 表达式中，首先通过 futures.stream() 将 futures 这个列表转换为一个流。
         * map 方法：
         *
         * 在流中，对每个 future 调用 future.join() 方法。join() 方法会阻塞当前线程，直到对应的 CompletableFuture 完成并返回结果。
         * 因此，map(future -> future.join()) 将每个 CompletableFuture 的结果提取出来，形成一个新的流，其中的元素类型是 String（假设 future 返回的是 String 类型的结果）。
         * collect 方法：
         *
         * 最后，使用 Collectors.toList() 将流中的结果收集为一个 List<String>。
         * 返回值 allCompleted：
         *
         * 最终，allCompleted 是一个 CompletableFuture<List<List<String>>> 对象，它表示当所有 futures 中的所有 CompletableFuture 都完成后，得到的结果。
         * 这个结果是一个嵌套的列表结构，外层列表包含了所有 futures 中的 CompletableFuture 的结果，每个内层列表则包含了一个 futures 中的一个 CompletableFuture 的结果。
         * 因此，这段代码的作用是等待多个 CompletableFuture 对象都完成，然后将它们的结果收集为一个嵌套的列表结构，并将最终的结果保存在 allCompleted 这个 CompletableFuture<List<List<String>>> 对象中。
         */
        CompletableFuture<List<List<String>>> allCompleted = allFutures.thenApply(v ->
                futures.stream()
                        .map(future -> future.join())
                        .collect(Collectors.toList()));

        // 获取最终的结果
        List<List<String>> results = allCompleted.join();

        // 输出结果
        results.forEach(System.out::println);

        // 关闭线程池
        customThreadPool.shutdown();
    }
}
